﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Toenda.Foundation.Data {
	/// <summary>
	/// Implements a template for a xml document
	/// </summary>
	public class XmlDocumentTemplate : List<XmlNodeTemplate> {
		/// <summary>
		/// Adds the xml info the the document
		/// </summary>
		public void AddDocumentInfo() {
			base.Add(new XmlNodeTemplate(XmlNodeTemplateType.DocumentInfo, "", ""));
		}

		/// <summary>
		/// Adds the xml info the the document
		/// </summary>
		/// <param name="isoLanguageType"></param>
		public void AddDocumentInfo(string isoLanguageType) {
			base.Add(new XmlNodeTemplate(XmlNodeTemplateType.DocumentInfo, "", isoLanguageType));
		}

		/// <summary>
		/// Adds the xml info the the document
		/// </summary>
		/// <param name="xmlVersion"></param>
		/// <param name="isoLanguageType"></param>
		public void AddDocumentInfo(string xmlVersion, string isoLanguageType) {
			base.Add(new XmlNodeTemplate(XmlNodeTemplateType.DocumentInfo, xmlVersion, isoLanguageType));
		}

		/// <summary>
		/// Adds the root node to the document
		/// </summary>
		/// <param name="nodeName"></param>
		public void AddRootNode(string nodeName) {
			base.Add(new XmlNodeTemplate(XmlNodeTemplateType.RootNode, nodeName, ""));
		}

		/// <summary>
		/// Adds a node to the document
		/// </summary>
		/// <param name="nodeName"></param>
		public void AddNode(string nodeName) {
			base.Add(new XmlNodeTemplate(XmlNodeTemplateType.Node, nodeName, ""));
		}

		/// <summary>
		/// Adds a single element to the document
		/// </summary>
		/// <param name="elementName"></param>
		/// <param name="elementValue"></param>
		public void AddElement(string elementName, string elementValue) {
			base.Add(new XmlNodeTemplate(XmlNodeTemplateType.Element, elementName, elementValue));
		}

		/// <summary>
		/// Adds a single element with a single attribute to the document
		/// </summary>
		/// <param name="elementName"></param>
		/// <param name="elementValue"></param>
		/// <param name="attributeName"></param>
		/// <param name="attributeValue"></param>
		public void AddElement(string elementName, string elementValue, string attributeName, string attributeValue) {
			List<XmlAttributeTemplate> attributeList = new List<XmlAttributeTemplate>();
			attributeList.Add(new XmlAttributeTemplate(attributeName, attributeValue));

			base.Add(new XmlNodeTemplate(XmlNodeTemplateType.Element, elementName, elementValue, attributeList));
		}

		/// <summary>
		/// Adds a single element with a list of attributes to the document
		/// </summary>
		/// <param name="elementName"></param>
		/// <param name="elementValue"></param>
		/// <param name="attributeList"></param>
		public void AddElement(string elementName, string elementValue, List<XmlAttributeTemplate> attributeList) {
			base.Add(new XmlNodeTemplate(XmlNodeTemplateType.Element, elementName, elementValue, attributeList));
		}

		/// <summary>
		/// Adds a single element with child nodes to the document
		/// </summary>
		/// <param name="elementName"></param>
		/// <param name="tree"></param>
		public void AddElementWithChildNodes(string elementName, XmlDocumentTemplate tree) {
			base.Add(new XmlNodeTemplate(XmlNodeTemplateType.Element, elementName, ""));

			this.AddChildrenToElement(elementName, tree);
		}

		/// <summary>
		/// Adds a single element with a single attribute and with child nodes to the document
		/// </summary>
		/// <param name="elementName"></param>
		/// <param name="tree"></param>
		/// <param name="attributeName"></param>
		/// <param name="attributeValue"></param>
		public void AddElementWithChildNodes(string elementName, XmlDocumentTemplate tree, string attributeName, string attributeValue) {
			List<XmlAttributeTemplate> attributeList = new List<XmlAttributeTemplate>();
			attributeList.Add(new XmlAttributeTemplate(attributeName, attributeValue));

			base.Add(new XmlNodeTemplate(XmlNodeTemplateType.Element, elementName, "", attributeList));

			this.AddChildrenToElement(elementName, tree);
		}

		/// <summary>
		/// Adds a single element with a list of attributes and with child nodes to the document
		/// </summary>
		/// <param name="elementName"></param>
		/// <param name="tree"></param>
		/// <param name="attributeList"></param>
		public void AddElementWithChildNodes(string elementName, XmlDocumentTemplate tree, List<XmlAttributeTemplate> attributeList) {
			base.Add(new XmlNodeTemplate(XmlNodeTemplateType.Element, elementName, "", attributeList));

			this.AddChildrenToElement(elementName, tree);
		}

		/// <summary>
		/// Adds a list of child nodes to a element of the document
		/// </summary>
		/// <param name="elementName"></param>
		/// <param name="tree"></param>
		public void AddChildrenToElement(string elementName, XmlDocumentTemplate tree) {
			XmlNodeTemplate node = base.Find(item => {
				return item.Name == elementName;
			});

			node.ChildNodes.AddRange(tree);
		}

		/// <summary>
		/// Adds a list of child nodes to a element of the document
		/// </summary>
		/// <param name="elementName"></param>
		/// <param name="tree"></param>
		public void AddChildrenToElement(string elementName, string attributeName, XmlDocumentTemplate tree) {
			XmlNodeTemplate node = base.Find(item => {
				return item.Name == elementName && item.HasOnlySingleAttribute && item.AttributeName == attributeName;
			});
			
			node.ChildNodes.AddRange(tree);
		}
	}
}
